﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Windows.Input;
using SmartLib.Core;

namespace SmartLib.Core
{
	/// <summary>
	/// MVVM ViewModel Container
	/// </summary>
	/// <remarks>Injected into view, contains data models + commands</remarks>
	public class ViewModelBase : ObservableBase
	{
		///// <summary>
		///// 
		///// </summary>
		//protected readonly object SyncObj = new object();

		//private ICustomCompositeCommand _commands;
		//private TrackablePropertiesContainer _dataItems;

		//private string _name;

		///// <summary>
		///// Gets the trackable properties.
		///// </summary>
		///// <value>The trackable properties.</value>
		//public IDictionary<string, TrackableProperty> TrackableProperties
		//{
		//    get
		//    {
		//        InitializeDataItems();
		//        return _dataItems.TrackableProperties;
		//    }
		//}

		//#region IViewModel Members

		///// <summary>
		///// Gets or sets the name.
		///// </summary>
		///// <value>The name.</value>
		//public string Name
		//{
		//    get { return _name; }
		//    set { SetField(ref _name, value, "Name"); }
		//}

		///// <summary>
		///// Gets the data items.
		///// </summary>
		///// <value>The data items.</value>
		//public IDictionary<string, object> DataItems
		//{
		//    get
		//    {
		//        InitializeDataItems();
		//        return _dataItems;
		//    }
		//}

		///// <summary>
		///// Gets the commands.
		///// </summary>
		///// <value>The commands.</value>
		//public ICustomCompositeCommand Commands
		//{
		//    get
		//    {
		//        if (_commands == null)
		//        {
		//            lock (SyncObj)
		//            {
		//                if (_commands == null)
		//                    _commands = new CustomCompositeCommand();
		//            }
		//        }
		//        return _commands;
		//    }
		//}

		//#endregion

		///// <summary>
		///// Inits the values container.
		///// </summary>
		///// <returns></returns>
		//protected override IDictionary<string, object> InitValuesContainer()
		//{
		//    InitializeDataItems();
		//    return _dataItems;
		//}

		//private void InitializeDataItems()
		//{
		//    if (_dataItems == null)
		//    {
		//        lock (SyncObj)
		//        {
		//            if (_dataItems == null)
		//                _dataItems = new TrackablePropertiesContainer();
		//        }
		//    }
		//}

		///// <summary>
		///// Gets the command by name.
		///// <remarks>Uses 'Commands' container</remarks>
		///// </summary>
		///// <typeparam name="T"></typeparam>
		///// <param name="commandName">Name of the command.</param>
		///// <returns></returns>
		//protected virtual T GetCommand<T>(string commandName) where T : ICommand
		//{
		//    if (!Commands.ContainsCommand(commandName)) return default(T);
		//    ICustomDelegateCommand cmd = Commands[commandName];
		//    return (T)cmd;
		//}

		///// <summary>
		///// Gets the command by property name.
		///// <remarks>Uses 'Commands' container</remarks>
		///// </summary>
		///// <typeparam name="T"></typeparam>
		///// <param name="commandSelector">The command selector.</param>
		///// <returns></returns>
		//protected virtual T GetCommand<T>(Expression<Func<T>> commandSelector) where T : ICommand
		//{
		//    string propertyName = GetMemberName(commandSelector);
		//    return GetCommand<T>(propertyName);
		//}

		///// <summary>
		///// Gets the command by property name (auto-discovery).
		///// <remarks>Uses 'Commands' container</remarks>
		///// </summary>
		///// <typeparam name="T"></typeparam>
		///// <returns></returns>
		//protected virtual T GetCommand<T>() where T : ICommand
		//{
		//    string propertyName = new StackFrame(1, false).GetMethod().Name;
		//    if (propertyName.StartsWith("get_") || propertyName.StartsWith("set_"))
		//        propertyName = propertyName.Substring(4);
		//    return GetCommand<T>(propertyName);
		//}

		///// <summary>
		///// Sets the command.
		///// </summary>
		///// <typeparam name="T"></typeparam>
		///// <param name="propertySelector">The property selector.</param>
		///// <param name="value">The value.</param>
		///// <returns></returns>
		//protected virtual bool SetCommand<T>(Expression<Func<T>> propertySelector, T value) where T : ICommand
		//{
		//    string propertyName = GetMemberName(propertySelector);
		//    return SetCommand(propertyName, value);
		//}

		///// <summary>
		///// Sets the command.
		///// </summary>
		///// <typeparam name="T"></typeparam>
		///// <param name="value">The value.</param>
		///// <returns></returns>
		//protected virtual bool SetCommand<T>(T value) where T : ICommand
		//{
		//    string propertyName = new StackFrame(1, false).GetMethod().Name;
		//    if (propertyName.StartsWith("get_") || propertyName.StartsWith("set_"))
		//        propertyName = propertyName.Substring(4);
		//    return SetCommand(propertyName, value);
		//}

		///// <summary>
		///// Sets the command.
		///// </summary>
		///// <typeparam name="T"></typeparam>
		///// <param name="commandName">Name of the command.</param>
		///// <param name="value">The value.</param>
		///// <returns></returns>
		//protected virtual bool SetCommand<T>(string commandName, T value) where T : ICommand
		//{
		//    if (Commands.ContainsCommand(commandName))
		//    {
		//        var oldValue = GetCommand<T>(commandName);
		//        if (Equals(oldValue, value)) return false;

		//        Commands.UnregisterCommand(oldValue);
		//    }

		//    OnPropertyChanging(commandName);
		//    Commands.RegisterCommand(value);
		//    OnPropertyChanged(commandName);
		//    return true;
		//}

		///// <summary>
		///// Determines whether [is trackable property supported] [the specified instance].
		///// </summary>
		///// <typeparam name="T"></typeparam>
		///// <param name="instance">The instance.</param>
		///// <returns>
		///// 	<c>true</c> if [is trackable property supported] [the specified instance]; otherwise, <c>false</c>.
		///// </returns>
		//public bool IsTrackablePropertySupported<T>(T instance) where T : class
		//{
		//    InitializeDataItems();
		//    return _dataItems.IsTrackablePropertySupported(instance);
		//}

		///// <summary>
		///// Safely pulls out the value
		///// </summary>
		///// <typeparam name="TValueCast">The type of the value cast.</typeparam>
		///// <param name="key">The key.</param>
		///// <param name="value">The value.</param>
		///// <returns></returns>
		//public bool TryGetValue<TValueCast>(string key, out TValueCast value)
		//{
		//    object obj;
		//    bool result = DataItems.TryGetValue(key, out obj);
		//    value = result ? (TValueCast)obj : default(TValueCast);
		//    return result;
		//}

		///// <summary>
		///// Gets the value or default.
		///// </summary>
		///// <typeparam name="TValueCast">The type of the value cast.</typeparam>
		///// <param name="key">The key.</param>
		///// <returns></returns>
		//public TValueCast GetValueOrDefault<TValueCast>(string key)
		//{
		//    object obj;
		//    bool result = DataItems.TryGetValue(key, out obj);
		//    return result ? (TValueCast)obj : default(TValueCast);
		//}

		///// <summary>
		///// Adds the version.
		///// </summary>
		///// <param name="name">The name.</param>
		///// <param name="value">The value.</param>
		//public void AddVersion(string name, object value)
		//{
		//    if (TrackableProperties.ContainsKey(name))
		//    {
		//        TrackableProperties[name].AddVersion(value);
		//    }
		//}

		///// <summary>
		///// Resets the value.
		///// </summary>
		///// <param name="name">The name.</param>
		//public void ResetValue(string name)
		//{
		//    _dataItems.ResetValue(name);
		//}

		///// <summary>
		///// Releases unmanaged and - optionally - managed resources
		///// </summary>
		///// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
		///// <returns></returns>
		//protected override bool Dispose(bool disposing)
		//{
		//    if (!base.Dispose(disposing)) return false;

		//    if (_commands != null)
		//    {
		//        _commands.RegisteredCommands.OfType<IDisposable>().ForEach(cmd => cmd.Dispose());
		//        _commands.RegisteredCommands.Clear();
		//        _commands = null;
		//    }

		//    if (_dataItems != null)
		//    {
		//        var dispose = _dataItems as IDisposable;
		//        dispose.Dispose();
		//        //_dataItems.GetProperties().OfType<IDisposable>().ForEach(disposable => disposable.Dispose());
		//        //_dataItems.Values.OfType<IDisposable>().ForEach(disposable => disposable.Dispose());
		//        //_dataItems.Clear();
		//        _dataItems = null;
		//    }

		//    _name = null;

		//    return true;
		//}
	}
}